<!--
 * @message: 表格列表组件
-->
<template>
 <!-- table公共组件：现已集成常用的删除、修改、查看按钮及分页组件 -->
 <div class="table">
   <Table
     ref="table"
     :border="border"
     :columns="columns"
     :data="dataSource"
     :size="size"
     :loading="loading"
     :width="width"
     :stripe="stripe"
     :show-header="showHeader"
     :height="height"
     @on-selection-change="handleSelectionChange"
     :max-height="maxHeight">
      <template slot-scope="{ row, index }" slot="special">
        <div class="base-table-col" @mouseenter="handleMouseenter(index)">
          <template>
            <div class="base-col-left-body">
              <div class="base-left-top-body">
                <template v-for="item in TableKey">
                  <span :key="item.id" v-if="item.customEl ? (item.customEl.type !== 'select' && item.customEl.type !== 'select' && item.customEl.type !== 'redio') : item.label" class="base-left-top-id">{{item.label}}</span>
                  <Tooltip :key="item.id+6" placement="bottom-start" :content="val(row,item.key)" max-width="300" :disabled="!(val(row,item.key))">
                  <Tag :key="item.id+1" v-if="item.customEl!==undefined  && val(row,item.key) !== undefined && item.customEl.type === 'tag'" :color="item.customEl.color"  :style="[{width: item.minWidth + 'px'}, (item.style !== undefined)? item.style : null]">
                    {{val(row,item.key)}}
                  </Tag>
                   </Tooltip>
                  <span :key="item.id+2" v-if="item.customEl ===undefined"  :style="[{'min-width': item.minWidth + 'px'}, item.style !== undefined? item.style : null]" class="base-left-top-name">
                    <Tooltip placement="bottom-start" :content="val(row,item.key)" max-width="300" :disabled="!(val(row,item.key))">
                    <span :style="[{'min-width': item.minWidth + 'px'}, item.style !== undefined? item.style : null]">{{val(row,item.key) ? val(row,item.key) : '-'}}</span>
                    </Tooltip>
                  </span>
                </template>
              </div>
              <div class="base-left-bottom-body">
                <span class="base-left-bottom-update">创建人: </span>
                <span class="base-left-bottom-user">{{row.createUserName}}</span>
                <span class="base-left-bottom-update">创建时间: </span>
                <span class="base-left-bottom-name">{{row.gmtCreate}}</span>
                <template v-for="item in TableKey">
                  <span :key="item.id+3"  v-if="item.label != undefined  && item.customEl && item.customEl.type === 'select' && item.customEl.type !== 'redio'" class="base-left-bottom-update">{{item.label}}</span>
                  <i-select :key="item.id+4"  v-model="row.activeStatus" :size="item.customEl.size"  v-if="item.customEl!==undefined && item.customEl.type === 'select'" :style="[{'width': item.minWidth + 'px'}, item.style !== undefined? item.style : null]" @on-change="handleClickDrop($event, row)">
                     <i-option v-for="citem in item.customEl.elText" :key="citem.value" :value="citem.value">{{ citem.label }}</i-option>
                  </i-select>
                </template>
              </div>
            </div>
            <div class="base-col-operating-body" v-if="index === currIndex">
              <div v-if="updateBtnExtraFactor ? row[updateBtnExtraParam] === updateBtnExtraVal && updateBtn : updateBtn" class="base-col-operating-layout"><Icon type="ios-create-outline" color="#0481FF" class="base-col-operating-icon" @click="handleUpdate(row)"/><span>修改</span></div>
              <div v-if="selectBtn" class="base-col-operating-layout"><Icon type="ios-search" color="#0481FF" class="base-col-operating-icon" @click="handleView(row)"/><span>查看</span></div>
              <div v-if="deleteBtn" class="base-col-operating-layout"><Icon type="ios-trash" color="#0481FF" class="base-col-operating-icon" @click="handleRemove(row, index)"/><span>删除</span></div>
              <div v-if="resetBtn" class="base-col-operating-layout"><Icon type="ios-checkmark-circle" color="#0481FF" class="base-col-operating-icon" @click="handleReset(row, index)"/><span>重置</span></div>
              <div v-if="downloadBtn" class="base-col-operating-layout"><Icon type="md-download" color="#0481FF" class="base-col-operating-icon" @click="handleDownload(row, index)"/><span>下载</span></div>
              <div v-if="reduceBtn" class="base-col-operating-layout"><Icon type="ios-undo" color="#0481FF" class="base-col-operating-icon" @click="handleReduce(row, index)"/><span>还原</span></div>
              <div v-if="expandBtn" class="base-col-operating-layout"><Icon type="ios-more" color="#0481FF" class="base-col-operating-icon" @click="handleExpand(row)"/><span>{{expandBtnText}}</span></div>
              <Dropdown v-if="fileBtn" class="base-col-operating-more" transfer transfer-class-name="base-col-operating-dropdown"  @on-click="handleOperateFile($event, row, index)">
                <a href="javascript:void(0)">
                  <Icon type="ios-more" color="#0481FF" class="base-col-operating-icon"/>
                </a>
                <DropdownMenu slot="list">
                  <DropdownItem name="copy">复制到</DropdownItem>
                  <DropdownItem name="select">查看详情</DropdownItem>
                  <DropdownItem name="update">修改</DropdownItem>
                  <DropdownItem name="delete">删除</DropdownItem>
                </DropdownMenu>
              </Dropdown>
            </div>
            <div class="base-col-right-body">
              <div class="base-right-top-body">
                <span>{{row.fkSecretLevel}}</span>
              </div>
              <div class="base-right-bottom-body">
                最后编辑时间：
                <span class="base-left-bottom-name"> {{row.lastLoginTime ? row.lastLoginTime : '-'}} </span>
              </div>
            </div>
          </template>
        </div>
      </template>
    </Table>
    <Page
        v-if="isShowPage"
        :total="total"
        :current.sync="current"
        :show-elevator="showElevator"
        :show-sizer="showSizer"
        :transfer="true"
        :show-total="showTotal"
        class-name="page"
        :disabled ="isDisabled "
        @on-change="handleChange"
        @on-page-size-change="handelSizeChange"
      />
  </div>
</template>

<script>
import message from '../../utils/message'
import { typeOf } from '../../utils/verification'
import { deleteTableByPk, getTableData } from '../../api/modules/table'
import { uuid } from '../../utils/data'

export default {
  name: 'BaseTable',
  props: {
    tableItem: {
      type: Array,
      required: true
    },
    // 表格列的配置描述（必传）
    columns: {
      type: Array,
      require: true
    },
    // 请求地址(表格)
    action: {
      type: String,
      default: ''
    },
    // 表格尺寸
    size: {
      type: String,
      default: 'default'
    },
    // 是否显示间隔斑马纹
    stripe: {
      type: Boolean,
      default: true
    },
    // 是否显示纵向边框
    border: {
      type: Boolean,
      default: false
    },
    // 表格宽度
    width: {
      type: [String, Number],
      default: 'auto'
    },
    // 表格高度
    height: {
      type: [String, Number],
      default: ''
    },
    // 表格最大高度（固定表格表头时使用）
    maxHeight: {
      type: [String, Number],
      default: ''
    },
    // 导出时文件名（如果使用iview的导出的话）
    exportFilename: {
      type: String,
      default: '表格数据'
    },
    // 导出时其他配置
    exportParams: {
      type: Object,
      default: () => { return {} }
    },
    // 是否禁用分页组件
    isDisabled: {
      type: Boolean,
      default: false
    },
    // 是否显示表头
    showHeader: {
      type: Boolean,
      default: false
    },
    // 表格数据（当父组件没有传递action时，表格的数据将交由该参数控制，不传它，可能表格初始数据为空）
    tableData: {
      type: Array,
      default: () => [{}]
    },
    // 分页总大小（当父组件没有传递action时，表格的数据将交由该参数控制，不传它，可能表格初始数据为空）
    tableTotal: {
      type: Number,
      default: 0
    },
    // 是否显示分页
    showSizer: {
      type: Boolean,
      default: true
    },
    // 是否显示总数
    showTotal: {
      type: Boolean,
      default: true
    },
    // 是否显示快梯
    showElevator: {
      type: Boolean,
      default: true
    },
    // 静态按钮（非权限按钮，而是模块表格中所有按钮）
    publicBtn: {
      type: Array,
      default: () => { return ['update', 'delete', 'view'] }
    },
    // 是否自行处理分页数据处理，为true，当前组件将向父组件暴露处理分页的2个函数
    selfWithPage: {
      type: Boolean,
      default: false
    },
    // 父组件应该将搜索条件通过这个参数传递过来（不传可能造成分页与搜索条件无法同时使用）
    initParams: {
      type: Object,
      default: () => { return {} }
    },
    // 分页必传参数配置
    baseParams: {
      type: Object,
      default: () => { return { page: 'page', rows: 'rows' } }
    },
    // 表格是否加载（当父组件没有传递action时，表格的加载状态将交由该参数控制）
    isLoading: {
      type: Boolean,
      default: true
    },
    // 按钮权限code（菜单id）用于控制按钮显示与隐藏
    menuCode: {
      type: [Number, String],
      default: 1
    },
    // 如果使用下拉菜单，该参数用于控制开关的值(后台返回的字段名)
    dropField: {
      type: String,
      default: 'activeStatus'
    },
    // 下拉菜单的值
    selectList: {
      type: Array,
      default: () => { return [] }
    },
    // 模块id的名字（由后台控制）
    idName: {
      type: String,
      default: ''
    },
    // 删除接口
    removeDataByKey: {
      type: String,
      default: ''
    },
    // 是否在本组件初始化发送请求，传递false可以取消第一次请求
    isInitRequest: {
      type: Boolean,
      default: true
    },
    // 扩展按钮名称
    expandBtnText: {
      type: String,
      default: '扩展'
    },
    // 是否显示分页
    isShowPage: {
      type: Boolean,
      default: true
    },
    // 文件操作按钮
    fileBtn: {
      type: Boolean,
      default: false
    },
    // 更新按钮是否需额外条件控制(这个额外参数目前只能为后台返回的数据中某个参数，因此这个我们一般使用不到)
    updateBtnExtraFactor: {
      type: Boolean,
      default: false
    },
    // 搭配上一个参数使用(一般使用不到)
    updateBtnExtraParam: {
      type: String,
      default: ''
    },
    // 搭配上一个参数使用(一般使用不到)
    updateBtnExtraVal: {
      type: [String, Number, Boolean],
      default: 1
    }
  },
  data () {
    return {
      // 分页总大小
      total: 0,
      typeOf,
      current: 1,
      // 当用户传递了action，表格的加载状态交由该参数控制
      state: true,
      currIndex: null,
      // 表格数据
      dataSource: [],
      // 获取表格数据基本参数（比如一页总数，当前页）
      defaultParams: {
        [this.baseParams.page]: 1,
        [this.baseParams.rows]: 10
      },
      requestParams: ''
    }
  },
  computed: {
    // 获取存储在vuex中的权限按钮信息
    // 表格加载
    loading () {
      // 如果传了action，表示通过当前组件进行请求，加载将交由当前组件控制，反之交由父组件进行控制
      if (this.action) {
        return this.state
      }
      return this.isLoading
    },
    currRouteAuth () {
      const meta = this.$route.meta
      const btnAuthList = meta.btnAuthList || []
      return btnAuthList
    },
    // 更新按钮
    updateBtn () {
      return this.currRouteAuth.indexOf('修改') !== -1 && this.publicBtn.indexOf('update') !== -1
    },
    // 查看按钮
    selectBtn () {
      return this.currRouteAuth.indexOf('列表') !== -1 && this.publicBtn.indexOf('view') !== -1
    },
    // 删除按钮
    deleteBtn () {
      return this.currRouteAuth.indexOf('删除') !== -1 && this.publicBtn.indexOf('delete') !== -1
    },
    // 重置按钮（前一个判断的数据全有后台控制，后一个由前台控制）
    resetBtn () {
      return this.currRouteAuth.indexOf('重置') !== -1 && this.publicBtn.indexOf('reset') !== -1
    },
    // 下载
    downloadBtn () {
      return this.publicBtn.indexOf('download') !== -1
    },
    // 重置
    reduceBtn () {
      return this.currRouteAuth.indexOf('还原') !== -1 && this.publicBtn.indexOf('reduce') !== -1
    },
    // 扩展按钮1
    expandBtn () {
      return this.publicBtn.indexOf('expand') !== -1
    },
    // 键名抽取
    TableKey () {
      const keys = []
      const noKeys = ['updateTime', 'updateUserName', 'createUserName', 'createTime']
      this.tableItem.forEach((item, index) => {
        if (item.key !== undefined && noKeys.indexOf(item.key) === -1) {
          this.$set(item, 'id', uuid(16, 16))
          keys.push(item)
        }
      })
      return keys
    }
  },
  created () {
    /* 如果父组件传递了地址，那么我们就在当前组件中发送请求，反之父组件自己请求数据， */
    if (!this.action) {
      this.dataSource = this.tableData
      this.total = this.tableTotal
    } else if (this.isInitRequest) {
      this.getData()
    }
  },
  methods: {
    val (row, key) {
      // eslint-disable-next-line
      return eval("row."+key)
    },
    /**
     * 点击编辑
     * @param row 当前行数据
     * @param
     * @param index
     */
    handleUpdate (row) {
      // 交由父组件处理
      this.$emit('handleUpdate', row, 2)
    },
    /**
     * 查看
     */
    handleView (row) {
      // 交由父组件处理
      this.$emit('handleView', row, 3)
    },
    /**
     * 点击删除时触发
     * @param row 当前行数据
     * @param index
     */
    handleRemove (row, index) {
      message.modal.confirm('你确定要删除吗？', '此次操作将删除<span style="color: red">1</span>条记录', () => {
        if (this.idName !== '' && this.removeDataByKey !== '') {
          deleteTableByPk(this.removeDataByKey, row[this.idName]).then((data) => {
            message.message.success(data.message)
            // 重新请求数据
            this.getData()
          })
        } else {
          // 用户确定删除后交由父组件处理
          this.$emit('handleRemove', { row, index })
        }
      }, () => {
        message.message.success('取消成功')
      })
    },
    /**
     * 更新表格及分页数据（如果传递了action既表示在本组件中获取表格数据，那么该方法使用不到）
     * 可通过ref的通讯方式调用该方法
     * @param list 表格数据
     * @param total 分页总大小
     */
    publicSelfUpdateData (list = [], total = 0) {
      if (this.action) {
        console.warn('方法使用错误')
      }
      this.dataSource = list
      this.total = total
    },
    /**
     * 获取表格数据
     * @param params 额外参数，比如搜索关键字
     * @param defaultParams 基本参数，比如当前页等
     * @param initParams 该参数将由父组件进行传递
     */
    getData (params = '', isSearch = false, defaultParams = this.defaultParams, initParams = this.initParams) {
      this.requestParams = params
      // 判断搜索按钮
      if (isSearch) {
        const pageExpress = this.baseParams.page
        // 设置页码为1
        this.defaultParams[pageExpress] = 1
      }
      // 开启加载
      this.state = true
      // 请求数据
      getTableData(this.action, {
        ...defaultParams,
        ...initParams,
        ...params
      }).then(({ data }) => {
        if (typeOf(data) === 'object' || typeOf(data) === 'array') {
          // 表格数据
          this.dataSource = typeOf(data.list) === 'array' && data.list.length > 0 ? data.list : typeOf(data) === 'array' ? data : []
          this.current = data.pageNum && data.pageNum > 0 ? data.pageNum : 1
          this.total = data.total
        } else {
          this.dataSource = []
          this.total = 0
          this.current = 1
        }
        // 关闭加载
        this.state = false
      }).catch(error => {
        message.message.error(error.message ? error.message : '查询出错,请检查后重试或者联系管理员')
        this.state = false
        throw new Error(error)
      })
    },
    /**
     * 页码改变的回调，返回改变后的页码
     * @param page
     */
    handleChange (page) {
      const pageExpress = this.baseParams.page
      this.defaultParams[pageExpress] = page
      if (this.selfWithPage) {
        this.$emit('handleChange', page)
      } else {
        this.getData(this.requestParams)
      }
    },
    /**
     * 切换每页条数时的回调，返回切换后的每页条数
     * @param rows
     */
    handelSizeChange (rows) {
      const rowsExpress = this.baseParams.rows
      this.defaultParams[rowsExpress] = rows
      if (this.selfWithPage) {
        this.$emit('handelSizeChange', rows)
      } else {
        this.getData(this.requestParams)
      }
    },
    /**
     * 如果表格有多选功能，选项发生变化时触发
     * @param selection
     */
    handleSelectionChange (selection) {
      // 交由父组件处理
      this.$emit('handleSelectionChange', selection)
    },
    /**
     * 导出表格数据
     */
    publicExportData () {
      this.$refs.table.exportCsv({
        filename: this.exportFilename,
        ...this.exportParams
      })
    },
    /**
     *  重置时触发（如果有该功能的话）
     * @param row
     * @param index
     */
    handleReset (row, index) {
      message.modal.confirm('重置密码', '你确定要重置当前用户密码?', () => {
        this.$emit('handleReset', row)
      }, () => {
        message.message.success('取消成功')
      })
    },
    /**
     * 点击下拉时触发
     * @param name
     */
    handleClickDrop (name, row) {
      this.$emit('handleClickDrop', name, row)
    },
    /**
     * 点击下载触发
     * @param row
     */
    handleDownload (row) {
      this.$emit('handleDownload', row)
    },
    /**
     * 点击还原触发
     * @param row
     */
    handleReduce (row) {
      this.$emit('handleReduce', row)
    },
    handleExpand  (row) {
      this.$emit('handleExpand', row)
    },
    /**
     * 鼠标移入单元格触发（现在只对文件管理模块有效）
     * @param index
     */
    handleMouseenter (index) {
      this.currIndex = index
    },
    /**
     * 点击文件夹操作时触发
     * @param name
     */
    handleOperateFolder (type, row) {
      this.$emit('handleOperateFolder', type, row)
    },
    /**
    * 点击文件操作
    * @author: Enzo
    * @date: 2019-10-31
    */
    handleOperateFile (type, row) {
      this.$emit('handleOperateFile', type, row)
    },
    /**
     * 下拉选项发生变化时触发
     * @param val
     */
    handleSelectChange (state, row) {
      this.$emit('handleSelectChange', { state, row })
    },
    /**
     * 鼠标移入单元格显示文字提示
     */
    handleTooltip (item) {
      this.$refs[item].render = (h, params) => {
      }
    }
  }
}
</script>

<style lang="scss" scoped>
  @import "../../assets/styles/scss/mixin";

  .table{
    width: auto;
    height: auto;
    .page{
      @include floatMixer(right);
      margin: 10px;
    }
    /deep/.ivu-tag-blue {
      text-align: center;
      border: 1px solid #2D8CF0;
      font-size: 12px;
      font-weight: 500;
    }
    /deep/.ivu-select-selection {
      background: rgba(1,127,255,1);
      color: #ffff;
      border-radius: 2px;
    }
    /deep/.ivu-select-arrow {
      color: #ffff;
    }
    /deep/.ivu-table{
      border-top: 1px #E6E6E6 solid;
      /deep/.ivu-table-column-center,  /deep/.table-row-body{
        border-bottom: 0;
      }
      &:before{
        height: 0;
      }
      /* 表格偶数行样式 */
      .even{
      }
      /* 表格奇数行样式 */
      .odd{
      }
    }
  }
  /deep/ .ivu-table table {
      min-width: 1602px;
      overflow-x: auto;
  }
  .table-btn{
    font-size: 12px;
  }
  .base-col-operating-dropdown{
    /deep/.ivu-dropdown-menu{
      min-width: 80px;
      /deep/.ivu-dropdown-item{
        text-align: center;
        font-size: 12px !important;
        color: #017FFF;
      }
    }
  }
  .base-table-col{
    height: 80px;
    @include flexMixer(space-between);
    .base-col-left-body{
      @include flexMixer(center, flex-start, column);
      .base-left-top-body{
        @include flexMixer(flex-start);
        font-size: 14px;
        color: #6C779A;
        font-weight: 500;
        width: 1020px;
        span, /deep/.ivu-tag-text, /deep/.ivu-tooltip-rel {
          overflow: hidden;
          text-overflow:ellipsis;
          white-space: nowrap;
          vertical-align: middle;
        }
        /deep/.ivu-tag{
          padding: 0px;
          cursor: pointer;
        }
        /deep/.ivu-tag-text{
          width: 110px;
        }
        /deep/.ivu-tooltip-rel span{
          display: inline-block;
        }
        .base-left-top-img{
          width: 23px;
          height: auto;
          margin-right: 7px;
        }
        .base-left-top-name{
          cursor: pointer;
          font-size: 14px;
          color: #6C779A;
          font-weight: 500;
        }
        .base-left-top-id{
          cursor: pointer;
          color: #B3B3B3;
          margin-right: 5px;
        }
        .base-col-left-badge{
          margin-right: 20px;
          /deep/.ivu-badge-status-text{
            margin-left: 0;
            color: #333;
          }
        }
      }
      .base-left-bottom-body{
        margin-top: 8px;
        font-size: 12px;
        font-weight: 500;
        color: #666666;
        span {
          margin-right: 10px;
          cursor: pointer;
        }
        .base-left-bottom-update{
          color: #B3B3B3;
          flex-shrink: 0;
          display: inline-block;
        }
      }
    }
    .base-col-right-body{
      padding-right: 30px;
      height: 100%;
      @include flexMixer(flex-start,flex-end);
      padding-bottom: 10px;
      .base-right-top-body{
        @include flexMixer(flex-end);
        font-size: 14px;
        font-weight: 500;
        color: #017FFF ;
      }
      .base-right-bottom-body{
        font-size: 12px;
        font-weight: 500;
        color: #B3B3B3;
      }
    }
    .base-col-operating-body{
      height: 100%;
      @include flexMixer();
      .base-col-operating-layout{
        @include flexMixer(center, center, column)
        margin-right: 10px;
        span {
          font-size:  12px;
          color: #2D8CF0;
          cursor: pointer;
        }
        .base-col-operating-icon{
          font-size:  20px;
          font-weight: bold;
          cursor: pointer;
          margin: 3px;
        }
      }
    }
  }
  /deep/.table-row-body{
    /deep/.ivu-table-cell{
      padding: 0;
    }
  }
  .base-left-bottom-name {
    color: #6C779A;
    width: 150px;
    display: inline-block;

  }
  .base-left-bottom-user {
    color: #6C779A;
    width: 80px;
    display: inline-block;
  }
</style>
